﻿using System.Windows;
using System.Windows.Controls;
using Dsl.Ped.Framework.Common;
using Dsl.Ped.Framework.WPFControls.ProjectiveObject;

namespace Dsl.Ped.Framework.Projections.ObjectProjections.Block
{
    /// <summary>
    /// <see cref="BlockProjection"/> organize content into a block as follows:
    /// Vertical Orientation:
    ///     #HeaderProjection# #StartTag# 
    ///         #ContentProjection# 
    ///     #EndTag#
    /// 
    /// Horizontal Orientation:
    ///     #HeaderProjection# #StartTag# #ContentProjection# #EndTag#
    /// </summary>
    public class BlockProjection : ContentControl
    {
        #region Fields

        /// <summary>
        /// Gets or sets the <see cref="ContentPresenter"/> of the header of a block
        /// </summary>
        private ContentPresenter HeaderProjectionPresenter { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="ContentPresenter"/> of the content of a block
        /// </summary>
        private ContentPresenter ContentPresenter { get; set; }

        /// <summary>
        /// Start tag of a block (see #StartTag#)
        /// </summary>
        public static DependencyProperty StartTagProperty;

        /// <summary>
        /// End tag of a block (see #EndTag#)
        /// </summary>
        public static DependencyProperty EndTagProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that defines whether the block is organized horizontally or vertically
        /// </summary>
        public static DependencyProperty OrientationProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that refers to the header projection of a block (see #HeaderProjection)
        /// </summary>
        public static DependencyProperty HeaderProjectionProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that refers to the projective object
        /// </summary>
        public static DependencyProperty ProjectiveObjectProperty;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes static members of the <see cref="BlockProjection"/> class. 
        /// </summary>
        static BlockProjection()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BlockProjection), new FrameworkPropertyMetadata(typeof(BlockProjection)));
           
            StartTagProperty = DependencyProperty.Register(
                "StartTag", typeof(string), typeof(BlockProjection),
                    new FrameworkPropertyMetadata("("));

            EndTagProperty = DependencyProperty.Register(
                "EndTag", typeof(string), typeof(BlockProjection),
                    new FrameworkPropertyMetadata(")"));

            OrientationProperty = DependencyProperty.Register(
                "Orientation", typeof(Orientation), typeof(BlockProjection), new FrameworkPropertyMetadata(Orientation.Horizontal));

            HeaderProjectionProperty = DependencyProperty.Register(
                "HeaderProjection", typeof(IProjection), typeof(BlockProjection), new FrameworkPropertyMetadata(null));
        }

        #endregion

        #region Members

        /// <summary>
        /// Gets or sets the <see cref="StartTagProperty"/> (see #StartTag#)
        /// </summary>
        public string StartTag
        {
            get { return (string)GetValue(StartTagProperty); }
            set { SetValue(StartTagProperty, value); }
        }

        /// <summary>
        /// Gets or sets the <see cref="EndTagProperty"/> (see #EndTag#)
        /// </summary>
        public string EndTag
        {
            get { return (string)GetValue(EndTagProperty); }
            set { SetValue(EndTagProperty, value); }
        }

        /// <summary>
        /// Gets or sets the orientation of a <see cref="BlockProjection"/>
        /// (Vertical / Horizontal block)
        /// </summary>
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        /// <summary>
        /// Gets or sets the <see cref="IProjection"/> of the header of a block
        /// </summary>
        public IProjection HeaderProjection
        {
            get { return (IProjection)GetValue(HeaderProjectionProperty); }
            set { SetValue(HeaderProjectionProperty, value); }
        }

        #endregion

        #region Methods
        
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.HeaderProjectionPresenter = (ContentPresenter)GetTemplateChild("PART_HeaderProjection");
            this.HeaderProjectionPresenter.Content = HeaderProjection.View;

            this.ContentPresenter = (ContentPresenter)this.GetTemplateChild("PART_Content");

            if (Content != null)
            {
                if (Content is IProjective)
                {
                    var projectiveObjectUserControl = new ProjectiveObjectUserControl();
                    projectiveObjectUserControl.ProjectiveObject = Content as IProjective;
                    projectiveObjectUserControl.IsTabStop = false;

                    this.ContentPresenter.Content = projectiveObjectUserControl;
                }
                else if (Content is IProjection)
                {
                    this.ContentPresenter.Content = (Content as IProjection).View;
                }
                else
                {
                    this.ContentPresenter.Content = Content.ToString();
                }
            }
        }

        #endregion
    }
}
